package com.xmmj.baselibrary.base.activity.mvvm

import android.content.Context
import android.content.Intent
import androidx.lifecycle.*
import com.xmmj.baselibrary.base.activity.mvvm.bean.*
import com.xmmj.baselibrary.base.application.BaseApplication
import com.xmmj.baselibrary.base.dialog.BaseMvvmDialog
import com.xmmj.baselibrary.base.event.BaseEvent
import com.xmmj.baselibrary.base.event.LoadEvent
import com.xmmj.baselibrary.base.fragment.BaseMvvmFragment
import com.xmmj.baselibrary.utils.Generic
import io.reactivex.functions.Action
import kotlinx.coroutines.*
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext

open class BaseViewModel<M : BaseModel?>(model: M?) : ViewModel(), IBaseViewModel {
    var mModel: M? = null

    init {
        mModel = model
    }

    constructor() : this(null) {
        mModel = Generic.getSuperclassType(this, 0)
    }

    var showLoadingLiveData: MutableLiveData<Boolean>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
        private set

    var hideLoadingLiveData: MutableLiveData<Void?>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
        private set

    var toastLiveData: MutableLiveData<String>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
        private set

    var showEmptyLiveData: MutableLiveData<EmptyBean>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
        private set

    var showErrorLiveData: MutableLiveData<ErrorBean>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
        private set

    var reLoginLiveData: MutableLiveData<Void?>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
        private set

    var requestLiveData: MutableLiveData<Void?>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
        private set

    var finishLiveData: MutableLiveData<Void?>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
        private set

    var dismissLiveData: MutableLiveData<Void?>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
        private set

    var finishRefreshLiveData: MutableLiveData<Void?>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
        private set

    var finishLoadMoreLiveData: MutableLiveData<Boolean>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
        private set

    var setFragmentLiveData: MutableLiveData<FragmentBean>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
        private set

    var setResultLiveData: MutableLiveData<ResultBean>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
        private set

    var requestPermissionLiveData: MutableLiveData<PermissionBean>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
        private set

    lateinit var lifecycleOwner: LifecycleOwner

    val context: Context
        get() {
            return if (lifecycleOwner is BaseMvvmActivity<*, *>) {
                lifecycleOwner as BaseMvvmActivity<*, *>
            } else (if (lifecycleOwner is BaseMvvmFragment<*, *>) {
                (lifecycleOwner as BaseMvvmFragment<*, *>).context
            } else {
                (lifecycleOwner as BaseMvvmDialog<*, *>).context
            })!!
        }

    val applicationContext: Context
        get() {
            return context.applicationContext
        }

    override fun onAny(var1: LifecycleOwner?, var2: Lifecycle.Event?) {

    }

    override fun onCreate() {
        registerEventBus()
    }

    override fun onDestroy() {
        unregisterEventBus()
    }

    override fun onStart() {

    }

    override fun onStop() {

    }

    override fun onResume() {

    }

    override fun onPause() {

    }

    /**
     * 显示Loading
     */
    open fun showLoading(cancelable: Boolean) {
        showLoadingLiveData!!.postValue(cancelable)
    }

    /**
     * 隐藏Loading
     */
    open fun hideLoading() {
        hideLoadingLiveData!!.postValue(null)
    }

    /**
     * 吐司
     */
    open fun toast(text: String?) {
        toastLiveData!!.postValue(text)
    }

    /**
     * 显示空提示
     */
    open fun showEmpty(show: Boolean, imageId: Int, hintText: String) {
        showEmptyLiveData!!.postValue(
            EmptyBean(
                show,
                imageId,
                hintText
            )
        )
    }

    /**
     * 显示错误
     */
    open fun showError(imageId: Int, errorText: String, btnText: String) {
        showErrorLiveData!!.postValue(
            ErrorBean(
                imageId,
                errorText,
                btnText
            )
        )
    }

    /**
     * 设置Fragment
     */
    open fun setFragment(containerViewId: Int, fragment: androidx.fragment.app.Fragment) {
        setFragmentLiveData!!.postValue(FragmentBean(containerViewId, fragment))
    }

    /**
     * 重新登录
     */
    open fun onReLogin() {
        reLoginLiveData!!.postValue(null)
    }

    /**
     * 发起请求
     */
    open fun onRequest() {
        requestLiveData!!.postValue(null)
    }

    /**
     * 关闭Activity
     */
    open fun finishActivity() {
        finishLiveData!!.postValue(null)
    }

    /**
     * 隐藏对话框
     */
    open fun dismiss() {
        dismissLiveData!!.postValue(null)
    }

    /**
     * 结束刷新动画
     */
    open fun finishRefresh() {
        finishRefreshLiveData!!.postValue(null)
    }

    /**
     * 结束加载更多动画
     */
    open fun finishLoadMore(noMoreData: Boolean) {
        finishLoadMoreLiveData!!.postValue(noMoreData)
    }

    /**
     * 设置返回值
     */
    open fun setResult(resultCode: Int, intent: Intent?) {
        setResultLiveData!!.postValue(ResultBean(resultCode, intent))
    }

    /**
     * 请求权限
     */
    open fun requestPermission(
        permissions: Array<String>,
        successAction: Action,
        cancelAction: Action?,
        description: String?
    ) {
        requestPermissionLiveData!!.postValue(
            PermissionBean(
                permissions,
                successAction,
                cancelAction,
                description
            )
        )
    }

    /**
     * 携程（会自动监听Activity/Fragment/Dialog的生命周期）
     */
    open fun launch(
        context: CoroutineContext = EmptyCoroutineContext,
        start: CoroutineStart = CoroutineStart.DEFAULT,
        block: suspend CoroutineScope.() -> Unit,
        error: (suspend CoroutineScope.(Exception) -> Unit)
    ) = viewModelScope.launch {
        try {
            block()
        } catch (e: Exception) {
            error(e)
        }
    }

    /**
     * 携程（会自动监听Activity/Fragment/Dialog的生命周期）
     */
    open fun launch(
        context: CoroutineContext = EmptyCoroutineContext,
        start: CoroutineStart = CoroutineStart.DEFAULT,
        block: suspend CoroutineScope.() -> Unit
    ) = viewModelScope.launch {
        try {
            block()
        } catch (e: Exception) {
            BaseApplication.errorHandle?.handleError(e, this@BaseViewModel)
        }
    }

    /**
     * 发送EventBus事件
     */
    override fun postEvent(event: BaseEvent) {
        EventBus.getDefault().post(event)
    }

    /**
     * 发送EventBus的粘性事件
     */
    override fun postStickyEvent(event: BaseEvent) {
        EventBus.getDefault().postSticky(event)
    }

    /**
     * 发送重载事件（通知每个页面进行刷新）
     */
    override fun postReLoadEvent() {
        postEvent(LoadEvent(LoadEvent.RELOAD))
    }

    /**
     * 注册EventBus
     */
    override fun registerEventBus() {
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this)
        }
    }

    /**
     * 注销EventBus
     */
    override fun unregisterEventBus() {
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this)
        }
    }

    /**
     * 订阅EventBus的事件
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    override fun <T : BaseEvent> subscribe(event: T) {
        if (event is LoadEvent && event.code == LoadEvent.RELOAD) {
            onRequest()
        }
    }

    /**
     * 订阅EventBus的粘性事件
     */
    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    override fun <T : BaseEvent> subscribeBySticky(event: T) {
        if (event is LoadEvent && event.code == LoadEvent.RELOAD) {
            onRequest()
        }
    }
}